#import "myController.h"
#import "ErrorAlert.h"
#import "CustomNSString.h"



@implementation myController


- (void) awakeFromNib 
{
	isSaveSettings = FALSE;
	
	// ウィンドウの自動保存名セット（名前セットしたら自動保存してくれる）
	[ theWindow setFrameAutosaveName : @"Window SavedName" ];
	[ theDebugWindow setFrameAutosaveName : @"DebugWindow SavedName" ];
	[ theMecabWindow setFrameAutosaveName : @"MecabWindow SavedName" ];

	dir = [ [ self Util_GetMyAppDirectory ] retain ];

	saykana = [ [ NSString stringWithString : @"/usr/local/bin/SayKana" ] retain ];
	[ self checkCommand : saykana ];

	mecab   = [ [ NSString stringWithString : @"/opt/local/bin/mecab"   ] retain ];
	[ self checkCommand : mecab ];
	shellscript = [ [[NSBundle mainBundle] pathForResource : @"mecab"
													ofType : @"sh" ] retain ];
	
	// テキストビューの内側の余白の設定
	[ theTextView setTextContainerInset : NSMakeSize(2, 2) ];
	[ theDebugTextView setTextContainerInset : NSMakeSize(2, 2) ];
	[ theMecabTextView setTextContainerInset : NSMakeSize(2, 2) ];
	
	// テキストビューのフォントとサイズの設定(Osaka最高)
	[ theTextView setFont : [ NSFont fontWithName : @"Osaka"
											 size : 12.0 ] ];
	[ theDebugTextView setFont : [ NSFont fontWithName : @"Osaka"
												  size : 12.0 ] ];
	[ theMecabTextView setFont : [ NSFont fontWithName : @"Osaka"
												  size : 12.0 ] ];

	// ウィンドウの最小サイズをセット
	[ theWindow setMinSize : NSMakeSize(300, 150) ];
	[ theDebugWindow setMinSize : NSMakeSize(200, 150) ];
	[ theMecabWindow setMinSize : NSMakeSize(200, 150) ];

	// 通知センターの取得＆通知名
	NSString *myAppNotification = @"VoiceunderReadingMessageNamed";
	nCenter = [ NSDistributedNotificationCenter defaultCenter ];

	// オブサーバーの追加
	[ nCenter addObserver : self
				 selector : @selector(receive:)
					 name : myAppNotification
				   object : nil
	   suspensionBehavior : NSNotificationSuspensionBehaviorDeliverImmediately ];
}


/*
 コマンドが存在するかチェック
 */
- (void)checkCommand : (NSString *)path
{
	BOOL isExist = [ [NSFileManager defaultManager] fileExistsAtPath : path 
								   isDirectory : nil ];
	
	if (! isExist) {
		NSString *tmp = [ NSString stringWithFormat : @"NotFound %@. Voiceunder is finished.", path ];
		[ ErrorAlert ErrorAlertMessage : tmp
							 ErrorCode : -10 ];
		[ ErrorAlert ApplicationFinished ];
	}
}


/*
 漢字混じりの文を平仮名にする
 mcccコマンド、mecabを利用
 */
- (NSString *) executeMecab : (NSString *)_message
{
	NSTask *task = [ [ NSTask alloc ] init ];	//Task=UNIXコマンド実行
	//	NSPipe *pError = [ NSPipe pipe ];	//エラー出力先
	NSPipe *pOutput = [ NSPipe pipe ];	//標準出力先
	
	[ task setLaunchPath : shellscript ];
	[ task setArguments : [ NSArray arrayWithObjects : _message, mecab, dir, nil ] ];	//渡す引数
	
	[ task setStandardOutput : pOutput ];
	//	[ task setStandardError : pError ];
	
	[ task launch ];	//実行
	[ task waitUntilExit ];	//終了まで待つ
	
	{
		//エラーのデータ
		//		NSData *dataError = [ [ pError fileHandleForReading ] availableData ];
		//エラー出力
		//NSLog( [ NSString stringWithFormat : @"error-%s", [ dataError bytes ] ] );
		
		// 確認用
		//[ ErrorAlert ErrorAlertMessage : [ NSString stringWithFormat : @"error-%s", [ dataError bytes ] ]
		//	ErrorCode : -10 ];
		
		
		//標準出力データ
		NSData *dataOutput = [ [ pOutput fileHandleForReading ] availableData ];

		[ task release ];
		
		//標準出力
		return [ [ [NSString alloc] initWithData : dataOutput
									   encoding  : NSUTF8StringEncoding ] autorelease ];
	}
}


/*
 mebacを使って漢字処理
 */
- (NSString *) HiraFromKanji : (NSString *)_message
{
	NSString *nsResult = [ self executeMecab : _message ];
	[ theMecabTextView setString : nsResult ];
	
	// nsResultにはMecabWindowに出力される形式であるため
	// 以下の処理で「読み上げ」に必要な部分を抜き出す
	
	// 改行区切りのarray
	NSArray *nbest_array = [ nsResult componentsSeparatedByString : @"\n" ];
		
	// 解析結果から読み上げ文字列生成
	int count = [nbest_array count] - 2;	// 最後に余計なデータが２行入る
	NSMutableString *message = [ [NSMutableString alloc] init ];	// 読み上げに使う文字列をここにappend
	
	NSArray *nbest_result;	// タブ区切りのarray
	NSString *wordclass;
	NSString *yomi;
	
	for (int i=0; i<count; i++) {
		nbest_result = [[nbest_array objectAtIndex:i] componentsSeparatedByString : @"\t"]; 
		
		NSArray *array2 = [[nbest_result objectAtIndex:1] componentsSeparatedByString : @","];
		wordclass = [ array2 objectAtIndex : 1 ];	// 「副詞」とか「動詞」とか「数」とか入る
		yomi = [ array2 objectAtIndex : [array2 count]-1 ];	// 発音
		
		if ( [yomi compare : @"*"] == NSOrderedSame ) {	// 発音がない場合
			if ( [wordclass compare:@"数"] == NSOrderedSame ) {	// 数である場合
				[ message appendString : [NSString stringWithFormat:@"<NUMK VAL=%@>+", [nbest_result objectAtIndex:0]] ];
			} else {
				[ message appendString : [nbest_result objectAtIndex:0] ];
			}
		} else {
			[ message appendString : yomi ];
		}
		
		wordclass = @"";
		yomi = @"";
	}
	
	return [ [ [NSString alloc] initWithString : message ] autorelease ];
}


/*
 読み上げる
 filepathがnilでなければファイルに保存
 */
- (void)saykana : (NSString *)_message
	   filepath : (NSString *)_filepath
{
	NSString *message = [ _message convertTo : @",,,"
										from : @"\n" ];

	// 全角数字を半角に
	message = [ message convertNumber ];

	// ゔ系の変換
	message = [ message convertToV ];
	
	// 半角カナを全角に
	message = [ message convertToZenkakuKana ];
	
	// 読み上げしなくなるので変換（mecab前にすることで意味を成す）
	message = [ message convertTo:@"＆" from:@"&" ];
	message = [ message convertTo:@"ー" from:@"～" ];
	message = [ message convertTo:@"" from:@"*" ];
	message = [ message convertTo:@"＠" from:@"@" ];
	message = [ message convertTo:@"「" from:@"｢" ];
	message = [ message convertTo:@"」" from:@"｣" ];

	// 読み上げ間隔を自然に
	message = [ message convertTo:@",," from:@"　" ];
	message = [ message convertTo:@"," from:@" " ];
	message = [ message convertTo:@"?" from:@"？" ];
	message = [ message convertTo:@"？,," from:@"?" ];

	// 漢字を片仮名に変換
	message = [ self HiraFromKanji : message ];	// mecab
	
	// 読み上げしなくなるので変換(mecab後にすることで意味を成す)
	message = [ message convertTo : @"ッ" from : @"っ" ];
	message = [ message convertTo : @"ッ" from : @"ッッ" ];
	
	// Debugウィンドウに表示
	[ theDebugTextView setString : message ];
	
	// 読み上げ時の性別取得
	NSString *sex;
	if ( [[theSex selectedCell] tag] == 0 ) {
		sex = [ NSString stringWithString : @"f1" ];
	} else {
		sex = [ NSString stringWithString : @"m1" ];
	}
	
	// 読み上げ時のスピード取得
	NSString *speed = [ theSpeedField stringValue ];
	NSTask *task;
	
	if ( _filepath != nil ) {	// ファイルの保存
		task = [ NSTask launchedTaskWithLaunchPath : saykana
										 arguments : [ NSArray arrayWithObjects : message
													  , @"-v"
													  , sex
													  , @"-s"
													  , speed
													  , @"-o"
													  , _filepath
													  , nil ] ];
	} else {
		task = [ NSTask launchedTaskWithLaunchPath : saykana
										 arguments : [ NSArray arrayWithObjects : message
													  , @"-v"
													  , sex
													  , @"-s"
													  , speed
													  , nil ] ];
	}

	[ task launch ];
	[ task waitUntilExit ];
	[ task release ];	
}


/*
 sayアクション
 */
- (IBAction)sayAction:(id)sender {
    NSString *message = [ theTextView string ];
	[ self saykana : message
		  filepath : nil ];
}


/*
 テキストのクリア
 */
- (IBAction)clearAction : (id)sender
{
	[ theTextView setString : @"" ];
	[ theDebugTextView setString : @"" ];
	[ theMecabTextView setString : @"" ];
}


/*
 これでモーダルダイアログ保存ができる。
 */
- (IBAction)saveAction : (id)sender
{
	NSSavePanel* aPanel = [ NSSavePanel savePanel ];
	[ aPanel setRequiredFileType : @"aiff" ];
	
	if( [aPanel runModal] == NSFileHandlingPanelOKButton ) {
		NSString *temp = [ theTextView string ];
		[ self saykana : temp 
			  filepath : [ aPanel filename ] ];
	}
}


/*
 自アプリケーションのディレクトリ取得
 */
- (NSString *)Util_GetMyAppDirectory
{
    // メインバンドルのパスを取得
    // ↓以下のような値が取得される
    //  "/...../hogehoge/XXX.app"
    NSString *pstrBundlePath = [ [ NSBundle mainBundle ] bundlePath ];
	
    //　"XXX.app"を除いたパスを通知
    return [ pstrBundlePath stringByDeletingLastPathComponent ];
}


/*
 デバッグウィンドウ表示
 */
- (IBAction)openDebugWindowAction : (id)sender
{
	[ theDebugWindow orderFront : nil ];
}


/*
 和布蕪ウィンドウ表示
 */
- (IBAction)openMecabWindowAction : (id)sender
{
	[ theMecabWindow orderFront : nil ];
}


/*
 外部アプリから読み上げメッセージ受け取り処理
 */
- (void)receive : (NSNotification *) notification
{
	[ theTextView setString : [notification object] ];
	[ self sayAction : nil ];
}


- (void)dealloc
{
	[ saykana release ];
	[ mecab release ];	
	[ dir release ];
	[ shellscript release ];
	[ theWindow release ];
	
	if (super == nil) {
		[ super dealloc ];
	}
}


@end
